<template>
    <div class="drag-resize" :class="{active: active, noActive: !active}" @mousedown="mousedown">
        <slot></slot>
        <div v-for="item in resize" 
            v-show="active" :class="item.handle" 
            class="resizable-handler" 
            :style="{cursor: item.direction}"
            @mousedown="resizeMouseDown(item.handle)"></div>
        <div v-for="item in resize" 
            v-show="active" 
            :class="item.handle" 
            class="square"></div>
    </div>
</template>

<script lang="ts">
import { Component, Vue, Watch, Emit, Prop } from 'vue-property-decorator'
import { parseNumber } from '@/utils/tools'

interface resize{
    handle: string;
    direction: string;
}
@Component({
    props: {
        active: Boolean,
        index: Number,
        componetInfo: Object
    }
})
export default class DragResize extends Vue {
    resize: resize[] = [
        {
            handle: 't',
            direction: 'n-resize'
        },
        {
            handle: 'b',
            direction: 's-resize'
        },
        {
            handle: 'r',
            direction: 'e-resize'
        },
        {
            handle: 'l',
            direction: 'w-resize'
        },
        {
            handle: 'tr',
            direction: 'ne-resize'
        },
        {
            handle: 'tl',
            direction: 'nw-resize'
        },
        {
            handle: 'br',
            direction: 'se-resize'
        },
        {
            handle: 'bl',
            direction: 'sw-resize'
        }
    ]
    componentPressStauts: boolean = false
    resizePressStatus: boolean = false
    activeHandle: string = ''

    /**
     * 设置data中的值
     */
    setData(this: any, target: string, value: any) {
        this[target] = value
    }
    dragResizeMouseMove(event: MouseEvent) {
        if (!this.resizePressStatus) {
            this.$emit('dargNodeMoveing', {
                moveX: event.movementX,
                moveY: event.movementY
            })
        } else {
            this.dargNodeResize(event, this.activeHandle)
        }
    }
    dargNodeResize(event: MouseEvent, activeHandle: string) {
        switch (activeHandle) {
            case 'l': // 向右变换节点
                this.resizeRight(event)
                return
            case 'r': // 向左变换节点
                this.resizeLeft(event)
                return
            case 'b': // 向下变换节点
                this.resizeBottom(event)
                return
            case 't': // 向上变换节点
                this.resizeTop(event)
                return
            case 'tr': // 向右上变换节点
                this.resizeRight(event)
                this.resizeTop(event)
                return
            case 'br': // 向右下变换节点
                this.resizeRight(event)
                this.resizeBottom(event)
                return
            case 'tl': // 向左上变换节点
                this.resizeLeft(event)
                this.resizeTop(event)
                return
            case 'bl': // 向左下变换节点
                this.resizeLeft(event)
                this.resizeBottom(event)
                return
        }
    }
    /**
     * 按住最右节点变换组件
    */
    resizeRight(event: MouseEvent) {
        let left = '0px',
            top = '0px',
            width = '0px',
            height = '0px'
        
        left = this.$props.componetInfo.style.left
        top = this.$props.componetInfo.style.top
        width = parseNumber(this.$props.componetInfo.style.width) + event.movementX + 'px'
        height = this.$props.componetInfo.style.height

        this.$emit('resizeNode', {index: this.$props.index, left, top, width, height})
    }
    /**
     * 按住最左节点变换组件
    */
    resizeLeft(event: MouseEvent) {
        let left = '0px',
            top = '0px',
            width = '0px',
            height = '0px'
        
        left = parseNumber(this.$props.componetInfo.style.left) + event.movementX + 'px'
        top = this.$props.componetInfo.style.top
        width = parseNumber(this.$props.componetInfo.style.width) - event.movementX + 'px'
        height = this.$props.componetInfo.style.height

        this.$emit('resizeNode', {index: this.$props.index, left, top, width, height})
    }
    /**
     * 按住最下节点变换组件
    */
    resizeBottom(event: MouseEvent) {
        let left = '0px',
            top = '0px',
            width = '0px',
            height = '0px'
        
        left = this.$props.componetInfo.style.left
        top = this.$props.componetInfo.style.top
        width = this.$props.componetInfo.style.width
        height = parseNumber(this.$props.componetInfo.style.height) + event.movementY + 'px'

        this.$emit('resizeNode', {index: this.$props.index, left, top, width, height})
    }
    /**
     * 按住最上节点变换组件
    */
    resizeTop(event: MouseEvent) {
        let left = '0px',
            top = '0px',
            width = '0px',
            height = '0px'
        
        left = this.$props.componetInfo.style.left
        top = parseNumber(this.$props.componetInfo.style.top) + event.movementY + 'px'
        width = this.$props.componetInfo.style.width
        height = parseNumber(this.$props.componetInfo.style.height) - event.movementY + 'px'

        this.$emit('resizeNode', {index: this.$props.index, left, top, width, height})
    }
    dragResizeMouseUp(event: MouseEvent) {
        this.setData('componentPressStauts', false)
        this.setData('resizePressStatus', false)
        document.removeEventListener('mousemove', this.dragResizeMouseMove)
        document.removeEventListener('mouseup', this.dragResizeMouseUp)
    }
    mousedown(event: MouseEvent) {
        this.$emit('activate', this.$props.index)
        this.setData('componentPressStauts', true)
        document.addEventListener('mousemove', this.dragResizeMouseMove)
        document.addEventListener('mouseup', this.dragResizeMouseUp)
    }
    resizeMouseDown(type: string) {
        this.resizePressStatus = true
        this.activeHandle = type
    }
}
</script>

<style lang="less">
@import '../../styles/variables.less';

@handle-size: 7px;
@square-size: 5px;
.drag-resize {
    position: absolute;
    &.noActive {
        &:hover {
            outline: 2px solid #0093dd;
        }
    }
    &.active {
        outline: 2px solid #0093dd;
    }
    .t, .b {
        left: 50%;    
    }
    .l, .r {
        top: 50%;
    }
    .resizable-handler {
        position: absolute;
        width: 14px;
        height: 14px;
        z-index: 1000;
        &.t {
            top: -@handle-size;
            margin-left: -@handle-size;
        }
        &.b {
            bottom: -@handle-size;
            margin-left: -@handle-size;
        }
        &.l {
            margin-top: -@handle-size;
            right: -@handle-size;
        }
        &.r {
            margin-top: -@handle-size;
            left: -@handle-size;
        }
        &.tr {
            top: -@handle-size;
            right: -@handle-size;
        }
        &.tl {
            top: -@handle-size;
            left: -@handle-size;
        }
        &.br {
            bottom: -@handle-size;
            right: -@handle-size;
        }
        &.bl {
            bottom: -@handle-size;
            left: -@handle-size;
        }
    }
    .square {
        position: absolute;
        width: 7px;
        height: 7px;
        background: #fff;
        border: 1px solid @primary-color;
        border-radius: 1px;
        z-index: 999;
        &.t {
            top: -@square-size;
            margin-left: -@square-size;
        }
        &.b {
            bottom: -@square-size;
            margin-left: -@square-size;
        }
        &.l {
            margin-top: -@square-size;
            right: -@square-size;
        }
        &.r {
            margin-top: -@square-size;
            left: -@square-size;
        }
        &.tr {
            top: -@square-size;
            right: -@square-size;
        }
        &.tl {
            top: -@square-size;
            left: -@square-size;
        }
        &.br {
            bottom: -@square-size;
            right: -@square-size;
        }
        &.bl {
            bottom: -@square-size;
            left: -@square-size;
        }
    }
}
</style>
